home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 003 / _gs / !GS / c / GXCOLOR < prev    next >
Text File  |  1991-10-26  |  7KB  |  253 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gxcolor.c */
  21. /* Private color procedures for Ghostscript library */
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gxfixed.h"            /* for gxmatrix.h */
  25. #include "gxmatrix.h"
  26. #include "gxdevice.h"            /* for gx_color_index */
  27. #include "gzcolor.h"
  28. #include "gzht.h"
  29. #include "gzstate.h"
  30.  
  31. /* Forward declarations */
  32. float gx_unit_param(P1(floatp));
  33. void gx_color_from_rgb(P1(gs_color *));
  34.  
  35. /* ------ Color setup routines ------ */
  36.  
  37. /* Set up a gray color.  This is an internal routine */
  38. /* for use by initialization and gx_remap_color. */
  39. void
  40. gx_set_gray_only(register gs_color *pcolor, floatp gray)
  41. {    pcolor->red = pcolor->green = pcolor->blue = pcolor->luminance =
  42.       gx_unit_param(gray) * max_color_param;
  43.     pcolor->luminance_set = 1;
  44.     pcolor->is_gray = 1;
  45.     pcolor->space = (byte)gs_color_space_DeviceGray;
  46. }
  47.  
  48. /* Set up an RGB color.  This is an internal routine */
  49. /* for use by gx_remap_color. */
  50. void
  51. gx_set_rgb_only(register gs_color *pcolor, floatp r, floatp g, floatp b)
  52. {    pcolor->red = gx_unit_param(r) * max_color_param;
  53.     pcolor->green = gx_unit_param(g) * max_color_param;
  54.     pcolor->blue = gx_unit_param(b) * max_color_param;
  55.     gx_color_from_rgb(pcolor);
  56. }
  57.  
  58. /* Set up an RGB color. */
  59. void
  60. gx_color_from_rgb(register gs_color *pcolor)
  61. {    if ( pcolor->red == pcolor->green && pcolor->green == pcolor->blue )
  62.        {    pcolor->luminance = pcolor->red;    /* pick any one */
  63.         pcolor->is_gray = pcolor->luminance_set = 1;
  64.        }
  65.     else
  66.        {    /* Compute luminance later */
  67.         pcolor->is_gray = pcolor->luminance_set = 0;
  68.        }
  69.     pcolor->space = (byte)gs_color_space_DeviceRGB;
  70. }
  71.  
  72. /* Force a parameter into the range [0..1]. */
  73. float
  74. gx_unit_param(floatp fval)
  75. {    if ( fval < 0.0 )
  76.         return 0.0;
  77.     else if ( fval > 1.0 )
  78.         return 1.0;
  79.     else
  80.         return fval;
  81. }
  82.  
  83. /* Remap the color in the graphics state. */
  84. void gx_render_color(P2(gs_color *, gs_state *));
  85. int
  86. gx_remap_color(gs_state *pgs)
  87. {    gs_color *pcolor = pgs->color;
  88.     gs_color mcolor;        /* color mapped by transfer procs */
  89. #define fcp(p) (pcolor->p / (float)max_color_param)
  90.     switch ( (gs_color_space)pcolor->space )
  91.        {
  92.     case gs_color_space_DeviceGray:
  93.         gx_set_gray_only(&mcolor,
  94.             (*pgs->transfer_procs.gray)(fcp(red)));    /* any one */
  95.         break;
  96.     case gs_color_space_DeviceRGB:
  97.         gx_set_rgb_only(&mcolor,
  98.             (*pgs->transfer_procs.red)(fcp(red)),
  99.             (*pgs->transfer_procs.green)(fcp(green)),
  100.             (*pgs->transfer_procs.blue)(fcp(blue)));
  101.         break;
  102.     default:
  103.         return_error(gs_error_undefined);
  104.        }
  105. #undef fcp
  106.     gx_render_color(&mcolor, pgs);
  107.     return 0;
  108. }
  109. void gx_color_render(P3(gs_color *, gx_device_color *, gs_state *));
  110. void
  111. gx_render_color(gs_color *pmcolor, gs_state *pgs)
  112. {    gx_color_render(pmcolor, pgs->dev_color, pgs);
  113. }
  114.  
  115. /* ------ Color conversion routines ------ */
  116.  
  117. /* Note: the color model conversion algorithms are taken from */
  118. /* Rogers, Procedural Elements for Computer Graphics, pp. 401-403. */
  119.  
  120. /* Compute (if necessary) and return the luminance of a color. */
  121. color_param
  122. gx_color_luminance(register gs_color *pcolor)
  123. {    if ( !pcolor->luminance_set )
  124.        {    pcolor->luminance =
  125.             (pcolor->red * (unsigned long)lum_red_weight +
  126.             pcolor->green * (unsigned long)lum_green_weight +
  127.             pcolor->blue * (unsigned long)lum_blue_weight +
  128.             (lum_all_weights / 2))
  129.             / lum_all_weights;
  130.         pcolor->luminance_set = 1;
  131.        }
  132.     return pcolor->luminance;
  133. }
  134.  
  135. /* Convert RGB to HSB */
  136. void
  137. gx_color_to_hsb(register gs_color *pcolor, color_param hsb[3])
  138. {
  139. #define rhue hsb[0]
  140. #define rsat hsb[1]
  141. #define rbri hsb[2]
  142.     if ( pcolor->is_gray )
  143.        {    rhue = 0;    /* arbitrary */
  144.         rsat = 0;
  145.         rbri = pcolor->red;    /* pick any one */
  146.        }
  147.     else
  148.        {    /* Convert rgb to hsb */
  149.         gs_color c;
  150.         color_param V, Temp;
  151.         long diff, H;
  152.         c.red = pcolor->red;
  153.         c.green = pcolor->green;
  154.         c.blue = pcolor->blue;
  155.         V = (c.red > c.green ? c.red : c.green);
  156.         if ( c.blue > V ) V = c.blue;
  157.         Temp = (c.red > c.green ? c.green : c.red);
  158.         if ( c.blue < Temp ) Temp = c.blue;
  159.         diff = V - Temp;
  160.         if ( V == c.red )
  161.             H = (c.green - c.blue) * (long)max_color_param / diff;
  162.         else if ( V == c.green )
  163.             H = (c.blue - c.red) * (long)max_color_param / diff + 2 * max_color_param;
  164.         else /* V == c.blue */
  165.             H = (c.red - c.green) * (long)max_color_param / diff + 4 * max_color_param;
  166.         if ( H < 0 ) H += 6 * max_color_param;
  167.         rhue = H / 6;
  168.         rsat = diff * (long)max_color_param / V;
  169.         rbri = V;
  170.        }
  171. #undef rhue
  172. #undef rsat
  173. #undef rbri
  174. }
  175.  
  176. /* Complete color specified by hsb */
  177. void
  178. gx_color_from_hsb(register gs_color *pcolor,
  179.   color_param hue, color_param saturation, color_param brightness)
  180. {    if ( saturation == 0 )
  181.        {    pcolor->red = pcolor->green = pcolor->blue = brightness;
  182.        }
  183.     else
  184.        {    /* Convert hsb to rgb. */
  185.         /* We rely on the fact that the product of two */
  186.         /* color_params fits into an unsigned long. */
  187.         ulong V = brightness;    /* force arithmetic to long */
  188.         color_param S = saturation;
  189. #define mcp max_color_param
  190. #define mcp6 (mcp / 6 + 1)
  191.         ulong F = (hue % mcp6) * 6;    /* ditto */
  192.         int I = hue / mcp6;
  193.         color_param M = V * (mcp - S) / mcp;
  194.         color_param N = V * (mcp - S * F / mcp) / mcp;
  195.         color_param K = V * (mcp - S * (mcp - F) / mcp) / mcp;
  196. #undef mcp6
  197. #undef mcp
  198.         color_param R, G, B;
  199.         switch ( I )
  200.            {
  201.         default: R = V; G = K; B = M; break;
  202.         case 1: R = N; G = V; B = M; break;
  203.         case 2: R = M; G = V; B = K; break;
  204.         case 3: R = M; G = N; B = V; break;
  205.         case 4: R = K; G = M; B = V; break;
  206.         case 5: R = V; G = M; B = N; break;
  207.            }
  208.         pcolor->red = R;
  209.         pcolor->green = G;
  210.         pcolor->blue = B;
  211.        }
  212.     gx_color_from_rgb(pcolor);    /* compute luminance */
  213. }
  214.  
  215. /* ------ Internal routines ------ */
  216.  
  217. /* Heapsort (algorithm 5.2.3H, Knuth vol. 2, p. 146), */
  218. /* modified for 0-origin indexing. */
  219. void
  220. gx_sort_ht_order(ht_bit *recs, uint N)
  221. {    uint l = N >> 1;
  222.     uint r = N - 1;
  223.     uint j;
  224.     ht_bit R;
  225.     if ( N <= 1 ) return;
  226. #define key(m) recs[m].mask
  227. #define K R.mask
  228.     while ( 1 )
  229.        {    if ( l > 0 )
  230.             R = recs[--l];
  231.         else
  232.            {    R = recs[r];
  233.             recs[r] = recs[0];
  234.             if ( --r == 0 )
  235.                {    recs[0] = R;
  236.                 break;
  237.                }
  238.            }
  239.         j = l;
  240.         while ( 1 )
  241.            {    uint i = j;
  242.             j = j + j + 1;
  243.             if ( j < r )
  244.                 if ( key(j) < key(j + 1) ) j++;
  245.             if ( j > r || K >= key(j) )
  246.                {    recs[i] = R;
  247.                 break;    /* to outer loop */
  248.                }
  249.             recs[i] = recs[j];
  250.            }
  251.        }
  252. }
  253.